from django.shortcuts import render, redirect
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django import http
import logging, re
from django.contrib.auth import login
from django_redis import get_redis_connection
from django.db import DatabaseError

from meiduo_mall.utils.response_code import RETCODE
from oauth.models import OAuthQQUser
from oauth.utils import generate_access_token_openid, check_access_token_openid
from users.models import User
from carts.utils import merge_cookie_to_redis
# Create your views here.


# 日志记录器
logger = logging.getLogger('django')


class QQAuthUserView(View):
    """实现OAuth2.0认证
    用来接收QQ互联重定向的请求
    """

    def get(self, request):
        """实现OAuth2.0认证"""
        # 接收Authorization Code
        code = request.GET.get('code')
        if not code:
            return http.HttpResponseForbidden('缺少code')

        # 创建oauth对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        try:
            # 通过Authorization Code获取Access Token
            access_token = oauth.get_access_token(code)
            # 通过Access Token获取openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseForbidden('QQ登录失败')

        # 使用openid查询该QQ用户是否绑定过美多商城用户
        try:
            # qq_user_model 是 OAuthQQUser对应的模型对象
            qq_user_model = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果openid没绑定美多商城用户，创建用户并绑定到openid
            access_token_openid = generate_access_token_openid(openid)
            context = {'access_token_openid': access_token_openid}
            return render(request, 'oauth_callback.html', context)
        else:
            # 如果openid已绑定美多商城用户，直接登入到美多商城系统
            # 先获取跟openid绑定的美多商城用户
            qq_user = qq_user_model.user

            # 状态保持
            login(request, qq_user)
            # 重定向到next
            next = request.GET.get('state')
            response = redirect(next)
            # 将用户名写入到cookie
            response.set_cookie('username', qq_user.username, expires=3600 * 24 * 14)

            # 登录成功后，合并购物车
            response = merge_cookie_to_redis(request=request, user=qq_user, response=response)

            # 响应结果
            return response

    def post(self, request):
        """使用openid绑定美多商城的用户"""
        # 接收参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        access_token_openid = request.POST.get('openid')

        # 校验参数
        # 判断参数是否齐全
        if not all([mobile, password, sms_code_client, access_token_openid]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')
        # 判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20位的密码')
        # 判断短信验证码是否一致
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})
        # 判断openid是否有效：错误提示放在sms_code_errmsg位置
        openid = check_access_token_openid(access_token_openid)
        if not openid:
            return render(request, 'oauth_callback.html', {'openid_errmsg': '无效的openid'})

        # 使用手机号判断用户是否存在
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果手机号对应的用户不存在，使用手机号新建用户
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 如果手机号对应的用户已存在，校验密码
            if not user.check_password(password):
                return render(request, 'oauth_callback.html', {'account_errmsg': '账号或密码错误'})

        # 使用openid绑定以上用户：使用openid和user创建一条记录
        try:
            OAuthQQUser.objects.create(user = user, openid = openid)
        except DatabaseError:
            return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'})

        # 状态保持
        login(request, user)
        # 重定向到next
        next = request.GET.get('state')
        response = redirect(next)
        # 将用户名写入到cookie
        response.set_cookie('username', user.username, expires=3600 * 24 * 14)

        # 登录成功后，合并购物车
        response = merge_cookie_to_redis(request=request, user=user, response=response)

        # 响应结果
        return response


class QQAuthURLView(View):
    """获取QQ登录扫码页面链接"""

    def get(self, request):
        """获取QQ登录扫码页面链接"""
        # 获取到next参数
        next = request.GET.get('next', '/')

        # 创建oauth对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)

        # 使用oauth对象调用工具方法获取QQ登录扫码页面链接
        login_url = oauth.get_qq_url()

        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})



